package com.winter.payService;

import com.alibaba.fastjson.JSONObject;
import com.winter.model.vo.HandleOrderVo;
import com.winter.util.Constants;
import com.winter.util.Result;
import com.winter.util.ResultCode;
import com.winter.util.json.JsonUtils;
import com.winter.util.payConfig.HttpUtil;
import com.winter.util.payConfig.WeiXinConfig;
import com.winter.util.payConfig.WeiXinPayUtil;
import com.winter.util.payConfig.XmlUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class WxPayService {

    private static final Logger logger = LoggerFactory.getLogger(WxPayService.class);

    @Autowired
    private AliPayService aliPayService;

    // 微信支付参数
    public Result wxPay(String body, String out_trade_no, String total_amount, String param) throws Exception {
        Result returnData = new Result();
        // 随机字符串
        String nonce_str = getRandomString(32);
        // 封装参数
        //金额
        Double d = Double.parseDouble(total_amount) * 100;
        String string = d.toString();
        string = string.substring(0, string.length() - 2);
        SortedMap<String, String> signParams = new TreeMap<String, String>();
        signParams.put("appid", WeiXinConfig.WX_APP_ID); // 微信开放平台审核通过的应用APPID
        signParams.put("mch_id", WeiXinConfig.WX_MACH_ID); // 微信支付分配的商户号
        signParams.put("nonce_str", nonce_str); // 随机字符串，不长于32位
        signParams.put("body", body); // 商品描述
        signParams.put("attach", param); // 附加数据，在查询API和支付通知中原样返回
        signParams.put("out_trade_no", out_trade_no); // 商户系统内部订单号
        signParams.put("total_fee", string); // 订单总金额，单位为分
        signParams.put("spbill_create_ip", WeiXinConfig.IP); // 用户端实际ip
        signParams.put("notify_url", WeiXinConfig.WX_PAY_NOTIFY_URL);// 接收微信支付异步通知回调地址
        signParams.put("trade_type", "APP"); // 支付类型
        String sign = WeiXinPayUtil.createSign("UTF-8", signParams);// 生成签名
        signParams.put("sign", sign); // 签名
        String requestXml = WeiXinPayUtil.getRequestXml(signParams);// 生成Xml格式的字符串
        // 调用统一支付接口
        requestXml = new String(requestXml.getBytes("utf-8"), "ISO-8859-1");
        String resXml = HttpUtil.postData("https://api.mch.weixin.qq.com/pay/unifiedorder", requestXml);
        // System.out.println("******************微信支付返回*******************\n" +
        // resXml);

        // 返回的result成功结果取出prepay_id：
        Map map = XmlUtil.doXMLParse(resXml);
        String return_code = (String) map.get("return_code");
        // System.out.println(JSONObject.fromObject(map).toString());
        // System.out.println(return_code);
        if (return_code.contains("SUCCESS")) {
            String prepay_id = (String) map.get("prepay_id"); // 获取到prepay_id
            String signs = (String) map.get("sign"); // 获取到prepay_id
            JSONObject jso = new JSONObject();
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            jso.put("appid", WeiXinConfig.WX_APP_ID); // app_id
            jso.put("partnerid", WeiXinConfig.WX_MACH_ID); // 微信商户账号
            jso.put("prepayid", prepay_id); // 预付订单id
            jso.put("package", "Sign=WXPay"); // 默认sign=WXPay
            jso.put("noncestr", nonce_str); // 自定义不重复的长度不长于32位
            jso.put("timestamp", timestamp); // 北京时间时间戳
            jso.put("sign", signs);

            SortedMap<String, String> signParam = new TreeMap<String, String>();
            signParam.put("appid", WeiXinConfig.WX_APP_ID); // app_id
            signParam.put("partnerid", WeiXinConfig.WX_MACH_ID); // 微信商户账号
            signParam.put("prepayid", prepay_id); // 预付订单id
            signParam.put("package", "Sign=WXPay"); // 默认sign=WXPay
            signParam.put("noncestr", nonce_str); // 自定义不重复的长度不长于32位
            signParam.put("timestamp", timestamp); // 北京时间时间戳
            String signAgain = WeiXinPayUtil.createSign("UTF-8", signParam);// 再次生成签名
            jso.put("sign", signAgain);
            // System.out.println("微信支付：+++++++++++++++++++++++++++++++++++++++++");
            // System.out.println(jso.toString());
            returnData.setCode(ResultCode.SUCCESS.code());
            returnData.setData(jso);
        } else {
            returnData.setMsg((String) map.get("return_msg"));
            returnData.setCode(2);
            returnData.setData(false);
        }
        return returnData;
    }


    /**
     * 微信回调
     */
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.info("-------------------------------------------begin notify");
        try {
            // 读取参数
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            logger.info("-------------------------------------------begin notify s:" + sb.toString());
            // 解析xml成map
            Map<String, String> m = new HashMap<String, String>();
            m = XmlUtil.doXMLParse(sb.toString());
            logger.info("-------------------------------------------begin notify param:" + m);
            // 过滤空 设置 TreeMap
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            Iterator it = m.keySet()
                           .iterator();
            while (it.hasNext()) {
                String parameter = (String) it.next();
                String parameterValue = m.get(parameter);

                String v = "";
                if (null != parameterValue) {
                    v = parameterValue.trim();
                }
                packageParams.put(parameter, v);
            }

            // 账号信息
            String key = WeiXinConfig.WX_APP_KEY; // key

            logger.info(packageParams.toString());
            // 判断签名是否正确
            if (WeiXinPayUtil.isTenpaySign("UTF-8", packageParams, key)) {
                // ------------------------------
                // 处理业务开始
                // ------------------------------
                String resXml = "";
                if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
                    // 这里是支付成功
                    ////////// 执行自己的业务逻辑////////////////
                    String mch_id = (String) packageParams.get("mch_id");
                    String openid = (String) packageParams.get("openid");
                    String is_subscribe = (String) packageParams.get("is_subscribe");
                    String out_trade_no = (String) packageParams.get("out_trade_no");
                    String total_fee = (String) packageParams.get("total_fee");
                    String attach = (String) packageParams.get("attach");

                    logger.info("mch_id:" + mch_id);
                    logger.info("openid:" + openid);
                    logger.info("is_subscribe:" + is_subscribe);
                    logger.info("out_trade_no:" + out_trade_no);
                    logger.info("total_fee:" + total_fee);

                    HandleOrderVo handleOrderVo = JSONObject.parseObject(attach, HandleOrderVo.class);
                    //HandleOrderVo handleOrderVo = JsonUtils.toObject(attach, HandleOrderVo.class);
                    aliPayService.handleOrder(handleOrderVo.getUserNo(), handleOrderVo.getDatumId(), total_fee, Constants.WX);
                    // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

                } else {
                    logger.info("支付失败,错误信息：" + packageParams.get("err_code"));
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
                }
                // ------------------------------
                // 处理业务完毕
                // ------------------------------
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } else {
                logger.info("通知签名验证失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 表示生成字符串的长度
    public static String getRandomString(int length) {
        length -= 14;
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        StringBuffer sb = new StringBuffer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        sb.append(sdf.format(new Date()));
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

}

